---
id: migration
title: Migration Guide
sidebar_label: Migration Guide
---

We changed the way developers integrate Flutter applications with Firebase in [mid 2020](https://github.com/FirebaseExtended/flutterfire/issues/2582). If you're currently using FlutterFire and wish
to upgrade to the latest recommended versions, follow this guide to help ease that process.

> If you're starting a fresh project, you can ignore this page and follow the [Getting Started](overview.mdx) documentation.

The table below shows the recommended package versions for each plugin this migration guide covers.

|                 Plugin  |                                  Version |
| ----------------------: | ---------------------------------------: |
|       `cloud_firestore` |         `^{{ plugins.cloud_firestore }}` |
|       `cloud_functions` |         `^{{ plugins.cloud_functions }}` |
|         `firebase_auth` |           `^{{ plugins.firebase_auth }}` |
|         `firebase_core` |           `^{{ plugins.firebase_core }}` |
|  `firebase_crashlytics` |    `^{{ plugins.firebase_crashlytics }}` |
|      `firebase_storage` |        `^{{ plugins.firebase_storage }}` |
|    `firebase_messaging` |      `^{{ plugins.firebase_messaging }}` |
|`firebase_remote_config` |  `^{{ plugins.firebase_remote_config }}` |

## Breaking Changes & Deprecations

Although breaking changes have been kept to a minimum, the substantial changes and improvements which have been made
required us to break a few things (for the greater good). Where possible, we've deprecated some "old ways" of
integrating FlutterFire, and you should aim to replace these deprecations as soon as possible.

## Migration Steps

### 1. Adding `firebase_core`

The FlutterFire plugins now depend on the `firebase_core` plugin. The plugin is responsible for connecting your Flutter
application to your Firebase project(s), and without it all other plugins will not work.

Add the plugin to your `pubspec.yaml` file within your project:

```yaml {4} title="pubspec.yaml"
dependencies:
  flutter:
    sdk: flutter
  firebase_core: "^{{ plugins.firebase_core }}"
```

### 2. Update Firebase Plugins

Update the Firebase plugins you use in your project to versions that are compatible with the new `firebase_core` plugin.

Edit the plugin versions in your `pubspec.yaml` file within your project to match the versions below:

```yaml {6,7,8,9,10,11} title="pubspec.yaml"
dependencies:
  flutter:
    sdk: flutter
  firebase_core: "^{{ plugins.firebase_core }}"
  # Newly reworked plugins covered by this migration guide:
  firebase_auth: "^{{ plugins.firebase_auth }}"
  firebase_crashlytics: "^{{ plugins.firebase_crashlytics }}"
  cloud_firestore: "^{{ plugins.cloud_firestore }}"
  cloud_functions: "^{{ plugins.cloud_functions }}"
  firebase_storage: "^{{ plugins.firebase_storage }}"
  firebase_messaging: "^{{ plugins.firebase_messaging }}"
  firebase_remote_config: "^{{ plugins.firebase_remote_config }}"
  # Updated to work with new core only plugins (no new changes):
  firebase_admob: "^{{ plugins.firebase_admob }}"
  firebase_analytics: "^{{ plugins.firebase_analytics }}"
  firebase_database: "^{{ plugins.firebase_database }}"
  firebase_dynamic_links: "^{{ plugins.firebase_dynamic_links }}"
  firebase_in_app_messaging: "^{{ plugins.firebase_in_app_messaging }}"
  firebase_performance: "^{{ plugins.firebase_performance }}"
```

Install the updated plugins by running the following command from the project root:

```bash
$ flutter pub get
```

We also recommend running `flutter clean` before continuing.

### 3. Platform Setup

Even though you may have already set up your platform to connect with Firebase, we recommend following the new
documentation steps for each platform to ensure everything is up-to-date.

Previously, it was possible to use FlutterFire without a "default" Firebase application. This has now changed, and all
platforms now require an underlying default Firebase app to be registered. The platform specific guides below show
you how to set up a default Firebase application:

#### A. [Android Installation](installation/android.mdx)

- Ensure that the `com.google.gms:google-services` plugin is up-to-date.
    - Update the version by changing the `classpath 'com.google.gms:google-services:4.3.3'` line in
      your `android/build.gradle` file to use version `4.3.3` or higher.
- Ensure your apps Gradle wrapper distribution version is v5 or higher, FlutterFire uses v5.6.2 for its examples.
    - Update the version by changing the `distributionUrl` value in your
      projects `android/gradle/wrapper/gradle-wrapper.properties` file.
        - e.g. setting to v5.6.2: `distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip`
- Ensure that you're not manually importing any Firebase Android SDK dependencies in your `android/app/build.gradle`
  files `dependencies { ... }` section.
    - e.g. remove any lines similar to: `implementation 'com.google.firebase:firebase-{PRODUCT}:{VERSION}`
    - The reworked plugins now automatically manage the versions of the Firebase SDKs used internally, so these are no
      longer required.
        - See the [overriding native sdk versions documentation](./overview.mdx#overriding-native-sdk-versions) if this
          is something you require.

- **Crashlytics only**: Remove the `maven { url 'https://maven.fabric.io/public' }` line from your
  projects `android/build.gradle` file.
- **Crashlytics only**: Remove the `classpath 'io.fabric.tools:gradle:1.31.2'` line from your
  projects `android/build.gradle` file.
- **Crashlytics only**: Remove the `apply plugin: 'io.fabric'` line from your projects `android/app/build.gradle` file.
- **Crashlytics only**: Remove any dependencies referencing `*com.crashlytics.sdk.android:crashlytics*` line from your
  projects `android/app/build.gradle` file (inside the `dependencies { .. }` block).
- **Crashlytics only**: Follow the new Android integration steps shown in
  the [FlutterFire Crashlytics installation documentation](https://firebase.flutter.dev/docs/crashlytics/overview#a-android)
  .

- **Messaging only**: Remove any dependencies referencing `*com.google.firebase:firebase-messaging*` line from your
  projects `android/app/build.gradle` file (inside the `dependencies { .. }` block).
- **Messaging only**: If you added the previous versions `intent-filter` to
  your `android/app/src/main/AndroidManifest.xml` file, remove it:

```diff
- <intent-filter>
-    <action android:name="FLUTTER_NOTIFICATION_CLICK" />
-    <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
```

- **Messaging only**: Messaging now supports v2 embedding, it's recommended that
  you [upgrade your Flutter app to use v2 embedding](https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects)
  if you haven't done so already.
- If your can't upgrade to v2 embedding yet, there are some additional manual steps you'll need to do before you can use
  messaging in your app. Please see the Android section of
  the [FlutterFire Messaging documentation](https://firebase.flutter.dev/docs/messaging/overview) for more information.
- If you were using v1 embedding on the previous version of messaging then note that the java class name has changed
  to `FlutterFirebaseMessagingBackgroundService` from `FlutterFirebaseMessagingService` and you may need to update this
  in your `MainActivity.java` file.

#### B. [iOS Installation](installation/ios.mdx)

These steps can also apply to macOS.

- If you manually import Firebase and configure it via `[FIRApp configure];` or `FirebaseApp.configure()` within your
  projects `ios/{projectName}/AppDelegate{.m/.swift}` file, you can now safely remove it - FlutterFire automatically
  handles this for you.

- **Crashlytics only**: Open your `ios/Runner.xcworkspace` workspace file with Xcode.
    1. From Xcode select `Runner` from the left-hand side project navigation.
    2. Select the `Build Phases` tab in the middle pane.
    3. Find a script in the list of Build Phases that contains `${PODS_ROOT}/Fabric/run` as the shell script. Once
       located, press the `x` on the right of the row to remove that script. If you can't find one then you can ignore
       this step.
- **Crashlytics only**: Follow the new iOS integration steps shown in
  the [FlutterFire Crashlytics installation documentation](https://firebase.flutter.dev/docs/crashlytics/overview#b-ios)
  .
- If you face CocoaPods issues when building, follow the steps below in
  the [CocoaPods could not find compatible versions for pod](#cocoapods-could-not-find-compatible-versions-for-pod)
  section.

- **Messaging only**: If you previously added the `FirebaseAppDelegateProxyEnabled` key with a `false` value to
  your `Info.plist` to disable swizzling; you can now remove it, the plugin now supports multiple delegates and will
  internally forward to any other plugins that may have previously registered a delegate.
- Additionally, swizzling is now no longer used on iOS and the plugin calls `addApplicationDelegate` on the
  FlutterPlugin Registrar instead. It is required for macOS however as the macOS registrar does not
  support `addApplicationDelegate`.

#### C. [Web Installation](installation/web.mdx)

### 4. Initialize FlutterFire

To ensure each plugin has a consistent API and to enable the possibility of some new features, you are now required to
initialize FlutterFire before performing any other Firebase related functionality.

The `firebase_core` package exposes a [`Firebase`](!firebase_core.Firebase) class, provides an
[`initializeApp`](!firebase_core.Firebase.initializeApp) method. This method should be called as soon as possible in
your application. It is responsible for ensuring the default app is ready, and bootstraps all additional FlutterFire
plugins which are installed.

To learn more, view the [Initializing FlutterFire](overview.mdx#initializing-flutterfire) documentation.

## Plugin Usage

Each plugin now provides a consistent API for integrating with Firebase. The example below shows how
the `cloud_firestore`
package previously created a new instance vs the new way:

```dart
// Before
Firestore firestore = Firestore();
// After
FirebaseFirestore firestore = FirebaseFirestore.instance;
```

If you'd like to a plugin with a secondary Firebase application, use the `instanceFor` method instead:

```dart
FirebaseApp secondaryApp = Firebase.app('SecondaryApp');

// Before
Firestore firestore = Firestore(app: secondaryApp);
// After
FirebaseFirestore firestore = FirebaseFirestore.instanceFor(app: secondaryApp);
```

To learn more about secondary Firebase app instances, view the [Initializing secondary apps](./core/usage.mdx)
documentation.

## Plugin Changes

### Core

- **DEPRECATED**: `FirebaseApp.configure` method is now deprecated in favor of the `Firebase.initializeApp` method.
- **DEPRECATED**: `FirebaseApp.allApps` method is now deprecated in favor of the `Firebase.apps` property.
    - Previously, `allApps` was asynchronous & is now synchronous.
- **DEPRECATED**: `FirebaseApp.appNamed` method is now deprecated in favor of the `Firebase.app` method.
- **BREAKING**: `FirebaseApp.options` getter is now synchronous.

- `FirebaseOptions` has been reworked to better match web property names:

    - **DEPRECATED**: `googleAppID` is now deprecated in favor of `appId`.
    - **DEPRECATED**: `projectID` is now deprecated in favor of `projectId`.
    - **DEPRECATED**: `bundleID` is now deprecated in favor of `bundleId`.
    - **DEPRECATED**: `clientID` is now deprecated in favor of `androidClientId`.
    - **DEPRECATED**: `trackingID` is now deprecated in favor of `trackingId`.
    - **DEPRECATED**: `gcmSenderID` is now deprecated in favor of `messagingSenderId`.
    - Added support for `authDomain`.
    - Added support for `trackingId`.
    - Required properties are now `apiKey`, `appId`, `messagingSenderId` & `projectId`.

- Added support for deleting Firebase app instances via the `delete` method on `FirebaseApp`.
- iOS: The default Firebase app is now automatically configured without needing to manually add Objective-C code to your
  iOS application.
- Added support for returning consistent error messages from `firebase-dart` plugin.
    - Any FlutterFire related errors now throw a `FirebaseException`.
- Added a `FirebaseException` class to handle all FlutterFire related errors.
    - Matching the web sdk, the exception returns a formatted "[plugin/code] message" message when thrown.
- Added support for `setAutomaticDataCollectionEnabled` & `isAutomaticDataCollectionEnabled` on a `FirebaseApp`
  instance.
- Added support for `setAutomaticResourceManagementEnabled` on a `FirebaseApp` instance.

- Android: Gradle build tools updated to 3.5.0 from 3.3.0.
- Android: Removed Gradle ‘hacks’ and upgrade Flutter SDK requirement from `>=1.12.13+hotfix.4` to `>=1.12.13+hotfix.5`
    - based on PR https://github.com/flutter/plugins/pull/2651
- Android: Switched to using Firebase BoM to manage SDK versions

### Authentication

Overall, Firebase Auth has been heavily reworked to bring it inline with the federated plugin setup along with adding
new features, documentation and many more unit and end-to-end tests. The API has mainly been kept the same, however
there are some breaking changes.

- **General**:

    - **BREAKING**: The `FirebaseUser` class has been renamed to `User`.
    - **BREAKING**: The `AuthResult` class has been renamed to `UserCredential`.
    - **NEW**: The `ActionCodeSettings` class is now consumable on all supporting methods.
        - **NEW**: Added support for the `dynamicLinkDomain` property.
    - **NEW**: Added a new `FirebaseAuthException` class (extends `FirebaseException`).
        - All errors are now returned as a `FirebaseAuthException`, allowing you to access the code & message associated
          with the error.
        - In addition, it is now possible to access the `email` and `credential` properties on exceptions if they exist.

- **`FirebaseAuth`**

    - **BREAKING**: Accessing the current user via `currentUser()` is now synchronous via the `currentUser` getter.
    - **BREAKING**: `isSignInWithEmailLink()` is now synchronous.
    - **DEPRECATED**: `FirebaseAuth.fromApp()` is now deprecated in favor of `FirebaseAuth.instanceFor()`.
    - **DEPRECATED**: `onAuthStateChanged` has been deprecated in favor of `authStateChanges()`.
    - **NEW**: Added support for `idTokenChanges()` stream listener.
    - **NEW**: Added support for `userChanges()` stream listener.
        - The purpose of this API is to allow users to subscribe to all user events without having to manually hydrate
          app state in cases where a manual reload was required (e.g. `updateProfile()`).
    - **NEW**: Added support for `applyActionCode()`.
    - **NEW**: Added support for `checkActionCode()`.
    - **NEW**: Added support for `verifyPasswordResetCode()`.
    - **NEW**: Added support for accessing the current language code via the `languageCode` getter.
    - **NEW**: `setLanguageCode()` now supports providing a `null` value.
        - On web platforms, if `null` is provided the Firebase projects default language will be set.
        - On native platforms, if `null` is provided the device language will be used.
    - **NEW**: `verifyPhoneNumber()` exposes a `autoRetrievedSmsCodeForTesting` property.
        - This allows developers to test automatic SMS code resolution on Android devices during development.
    - **NEW** (iOS): `appVerificationDisabledForTesting` setting can now be set for iOS.
        - This allows developers to skip ReCaptcha verification when testing phone authentication.
    - **NEW** (iOS): `userAccessGroup` setting can now be set for iOS & macOS.
        - This allows developers to share authentication states across multiple apps or extensions on iOS & macOS. For
          more information see
          the [Firebase iOS SDK documentation](https://firebase.google.com/docs/auth/ios/single-sign-on).

- **`User`**

    - **BREAKING**: Removed the `UpdateUserInfo` class when using `updateProfile` in favor of named arguments.
    - **NEW**: Added support for `getIdTokenResult()`.
    - **NEW**: Added support for `verifyBeforeUpdateEmail()`.
    - **FIX**: Fixed several iOS crashes when the Firebase SDK returned `nil` property values.
    - **FIX**: Fixed an issue on Web & iOS where a user's email address would still show after unlinking the
      email/password provider.

- **`UserCredential`**

    - **NEW**: Added support for accessing the user's `AuthCredential` via the `credential` property.

- **`AuthProvider`** & **`AuthCredential`**
    - **DEPRECATED**: All sub-class (e.g. `GoogleAuthProvider`) `getCredential()` methods have been deprecated in favor
      of `credential()`.
        - **DEPRECATED**: `EmailAuthProvider.getCredentialWithLink()` has been deprecated in favor
          of `EmailAuthProvider.credentialWithLink()`.
    - **NEW**: Supporting providers can now assign scope and custom request parameters.
        - The scope and parameters will be used on web platforms when triggering a redirect or popup
          via `signInWithPopup()` or `signInWithRedirect()`.

### Crashlytics

- **BREAKING**: Removal of Fabric SDKs and migration to the new Firebase Crashlytics SDK.
- **BREAKING**: The following methods have been removed as they are no longer available on the Firebase Crashlytics SDK:
    - `setUserEmail`
    - `setUserName`
    - `getVersion`
    - `isDebuggable`
- **BREAKING**: `log` now returns a Future. Calling `log` now sends logs immediately to the underlying Crashlytics SDK
  instead of pooling them in Dart.
- **BREAKING**: the methods `setInt`, `setDouble`, `setString` and `setBool` have been replaced by `setCustomKey`.
    - `setCustomKey` returns a Future. Calling `setCustomKey` now sends custom keys immediately to the underlying
      Crashlytics SDK instead of pooling them in Dart.
- **DEPRECATED**: `enableInDevMode` has been deprecated, use `isCrashlyticsCollectionEnabled`
  and `setCrashlyticsCollectionEnabled` instead.
- **DEPRECATED**: `Crashlytics` has been deprecated, use `FirebaseCrashlytics` instead.
- **NEW**: Custom keys that are automatically added by FlutterFire when calling `reportError` are now prefixed
  with `flutter_error_`.
- **NEW**: Calling `.crash()` on Android & iOS/macOS now reports a custom named exception to the Firebase Console. This
  allows you to easily locate test crashes.
    - Name: `FirebaseCrashlyticsTestCrash`.
    - Message: `This is a test crash caused by calling .crash() in Dart.`.
- **NEW**: `recordError` now uses a named native exception when reporting to the Firebase Console. This allows you to
  easily locate errors originating from Flutter.
    - Name: `FlutterError`.
- **NEW**: Added support for `checkForUnsentReports`.
    - Checks a device for any fatal or non-fatal crash reports that haven't yet been sent to Crashlytics.
    - See reference API docs for more information.
- **NEW**: Added support for `deleteUnsentReports`.
    - If automatic data collection is disabled, this method queues up all the reports on a device for deletion.
    - See reference API docs for more information.
- **NEW**: Added support for `didCrashOnPreviousExecution`.
    - Checks whether the app crashed on its previous run.
    - See reference API docs for more information.
- **NEW**: Added support for `sendUnsentReports`.
    - If automatic data collection is disabled, this method queues up all the reports on a device to send to
      Crashlytics.
    - See reference API docs for more information.
- **NEW**: Added support for `setCrashlyticsCollectionEnabled`.
    - Enables/disables automatic data collection by Crashlytics.
    - See reference API docs for more information.
- **NEW**: Added support for `isCrashlyticsCollectionEnabled`.
    - If the current Crashlytics instance is collecting reports - if false, then no crash reporting data is sent to
      Firebase.
    - See reference API docs for more information.
- **FIX**: Fixed a bug that prevented keys from being set on iOS devices.

### Firestore

Along with the below changes, the plugin has undergone a quality of life update to better support exceptions thrown. Any
Firestore specific errors now return a `FirebaseException` (see Core changes), allowing you to directly access the code
(e.g. permission-denied) and message.

- **`FirebaseFirestore`**:

    - **BREAKING**: Calling `settings()` now accepts a `Settings` instance.
    - **DEPRECATED**: Calling `document()` is deprecated in favor of `doc()`.
    - **DEPRECATED**: Calling `Firestore(app: app)` is now deprecated. Use `FirebaseFirestore.instance`
      or `FirebaseFirestore.instanceFor` instead.
    - **BREAKING**: `enablePersistence` has now been removed, see `settings()` instead.
    - **NEW**: Add `clearPersistence()` support.
    - **NEW**: Add `disableNetwork()` support.
    - **NEW**: Add `enableNetwork()` support.
    - **NEW**: Add `snapshotInSync()` support.
    - **NEW**: Add `terminate()` support.
    - **NEW**: Add `waitForPendingWrites()` support.

- **`CollectionReference`**:

    - **BREAKING**: Getting a collection parent document via `parent()` has been changed to a getter `parent`.
    - **DEPRECATED**: Calling `document()` is deprecated in favor of `doc()`.

- **`Query`**:

    - **BREAKING**: The internal query logic has been overhauled to better assert invalid queries locally.
    - **BREAKING**: `getDocuments`/`get` has been updated to accept an instance of `GetOptions` (see below).
    - **DEPRECATED**: Calling `getDocuments()` is deprecated in favor of `get()`.
    - **NEW**: Query methods are now chainable.
    - **NEW**: It is now possible to call same-point cursor based queries without throwing (e.g. calling `endAt()` and
      then `endBefore()` will replace the "end" cursor query with the `endBefore`).
    - **NEW**: Added support for `limitToLast`.

- **`QuerySnapshot`**:

    - **DEPRECATED**: `documents` has been deprecated in favor of `docs`.
    - **DEPRECATED**: `documentChanges` has been deprecated in favor of `docChanges`.
    - **NEW**: `docs` now returns a `List<QueryDocumentSnapshot>` vs `List<DocumentSnapshot>`. This doesn't break
      existing functionality.

- **`DocumentReference`**:

    - **BREAKING**: `setData`/`set` has been updated to accept an instance of `SetOptions` (see below,
      supports `mergeFields`).
    - **BREAKING**: `get()` has been updated to accept an instance of `GetOptions` (see below).
    - **BREAKING**: Getting a document parent collection via `parent()` has been changed to a getter `parent`.
    - **DEPRECATED**: `documentID` has been deprecated in favor of `id`.
    - **DEPRECATED**: `setData()` has been deprecated in favor of `set()`.
    - **DEPRECATED**: `updateData()` has been deprecated in favor of `update()`.

- **`DocumentSnapshot`**:

    - **BREAKING**: Getting a snapshots' data via the `data` getter is now done via the `data()` method.
    - **DEPRECATED**: `documentID` has been deprecated in favor of `id`.
    - **NEW**: Added support for fetching nested snapshot data via the `get()` method. If no data exists at the given
      path, a `StateError` will be thrown.

- **`DocumentChange`**:

    - **DEPRECATED**: Calling `document()` is deprecated in favor of `doc()`.

- **`WriteBatch`**:

    - **BREAKING**: `setData`/`set` now supports `SetOptions` to merge data/fields (previously this accepted a `Map`).
    - **DEPRECATED**: `setData()` has been deprecated in favor of `set()`.
    - **DEPRECATED**: `updateData()` has been deprecated in favor of `update()`.

- **`Transaction`**:

    - **BREAKING**: Transactions have been overhauled to address a number of issues:
        - Values returned from the transaction will now be returned from the Future. Previously, only primitive values (
          e.g. `String`) were supported. It is now possible to return values such as a `DataSnapshot`.
        - When manually throwing an exception, the context was lost and a generic `PlatformException` was thrown. You
          can now throw & catch on any exceptions.
        - The modify methods on a transaction (`set`, `delete`, `update`) were previously Futures. This has been updated
          to better reflect how transactions should behave - they are now synchronous and are executed atomically once
          the transaction handler block has finished executing.

- **`FieldPath`**:

    - **NEW**: The constructor has now been made public to accept a `List` of `String` values. Previously field paths
      were accessible only via a dot-notated string path. This meant attempting to access a field in a document with
      a `.` in the name (e.g. `foo.bar@gmail.com`) was impossible.

- **`GetOptions`**: New class created to support how data is fetched from Firestore (server, cache, serverAndCache).

- **`SetOptions`**: New class created to both `merge` and `mergeFields` when setting data on documents.

- **`GeoPoint`**:
    - **BREAKING**: Added latitude and longitude validation when constructing a new `GeoPoint` instance.

### Functions

- **`FirebaseFunctions`**:

    - **DEPRECATED**: Class `CloudFunctions` is now deprecated. Use `FirebaseFunctions` instead.
    - **DEPRECATED**: Calling `CloudFunctions.instance` or `CloudFunctions(app: app, region: region)` is now deprecated.
      Use `FirebaseFunctions.instance` or `FirebaseFunctions.instanceFor(app: app, region: region)` instead.
    - **DEPRECATED**: Calling `getHttpsCallable(functionName: functionName)` is deprecated in favor
      of `httpsCallable(functionName)`
    - **DEPRECATED**: `CloudFunctionsException` is deprecated in favor of `FirebaseFunctionsException`.
    - **NEW**: `FirebaseFunctionsException` now exposes a `details` property to retrieve any additional data provided
      with the exception returned by an HTTPS callable function.
    - **NEW**: Internally, instances of `FirebaseFunctions` are now cached and lazily loaded.
    - **NEW**: `httpsCallable` accepts an instance of `HttpsCallableOptions` (see below).

- **`HttpsCallable`**:

    - **DEPRECATED**: Setting `timeout` is deprecated in favor of using `HttpsCallableOptions` (see below).

- **`HttpsCallableResult`**:

    - **BREAKING**: `data` is now read-only, only its getter is exposed.
    - **FIX**: `HttpsCallableResult`'s `data` property can now return a Map, List or a primitive value. Previously the
      Web implementation incorrectly assumed that a Map was always returned by the HTTPS callable function.

- **`HttpsCallableOptions`**:
    - **NEW**: This new class has been created to support setting options for `httpsCallable` instances.

### Messaging

This plugin is now federated to allow integration with other platforms, along with upgrading underlying SDK versions.

We've also added lots of features which can be seen in the changelog below, however notably the biggest changes are:

- Removed all manual native code changes that were originally required for integration - this plugin works
  out of the box once configured with Firebase & APNs.
- Support for macOS.
- iOS background handler support.
- Android background handler debugging and logging support.
- Android V2 embedding support.
- Reworked API for message handling (Streams + explicit handlers).
- Fully typed Message & Notification classes (vs raw Maps).
- New Apple notification permissions & support.
- Detailed documentation.

- **`FirebaseMessaging`**:

    - **BREAKING**: `configure()` has been removed in favor of calling specific static methods which return Streams.
        - **Why?**: The previous implementation of `configure()` caused unintended side effects if called multiple
          times (either to register a different handler, or remove handlers). This change allows developers to be more
          explicit about registering handlers and removing them without effecting others via Streams.
    - **DEPRECATED**: Calling `FirebaseMessaging()` has been deprecated in favor of `FirebaseMessaging.instance`
      & `FirebaseMessaging.instanceFor()`.
    - **DEPRECATED**: `requestNotificationPermissions()` has been deprecated in favor of `requestPermission()`.
    - **DEPRECATED**: `deleteInstanceID()` has been deprecated in favor of `deleteToken()`.
    - **DEPRECATED**: `autoInitEnabled()` has been deprecated in favor of `isAutoInitEnabled`.
    - **NEW**: Added support for `isAutoInitEnabled` as a synchronous getter.
    - **NEW**: Added support for `getInitialMessage()`. This API has been added to detect whether a messaging containing
      a notification has caused the application to be opened via users interaction.
    - **NEW**: Added support for `deleteToken()`.
    - **NEW**: Added support for `getToken()`.
    - **NEW**: [Apple] Added support for `getAPNSToken()`.
    - **NEW**: [Apple] Added support for `getNotificationSettings()`. See `NotificationSettings` below.
    - **NEW**: [Apple] Added support for `requestPermission()`. See `NotificationSettings` below. New permissions such
      as `carPlay`, `crtiticalAlert`, `announcement` are now supported.
    - **NEW**: [Android] Added support for `sendMessage()`. The `sendMessage()` API enables support for sending FCM
      payloads back to a custom server from the device.
    - **NEW**: [Android] When receiving background messages on the separate background Dart executor whilst in debug,
      you should now see flutter logs and be able to debug/add breakpoints your Dart background message handler.
    - **NEW**: [Apple] Added support for `setForegroundNotificationPresentationOptions()`. By default, iOS devices will
      not show notifications in the foreground. Use this API to override the defaults. See documentation for Android
      foreground notifications.
    - **NEW** - [Android] Firebase Cloud Messages that contain a notification are now always sent to Dart regardless of
      whether the app was in the foreground or background. Previously, if a message came through that contained a
      notification whilst your app was in the foreground then FCM would not notify the plugin messaging service of the
      message (and subsequently your handlers in Dart) until the user interacted with it.

- **Event handling**:

    - Event handling has been reworked to provide a more intuitive API for developers. Foreground based events can now
      be accessed via Streams:
        - **NEW**: `FirebaseMessaging.onMessage` Returns a Stream that is called when an incoming FCM payload is
          received whilst the Flutter instance is in the foreground, containing a [RemoteMessage].
        - **NEW**: `FirebaseMessaging.onMessageOpenedApp` Returns a [Stream] that is called when a user presses a
          notification displayed via FCM. This replaces the previous `onLaunch` and `onResume` handlers.
        - **NEW**: `FirebaseMessaging.onBackgroundMessage()` Sets a background message handler to trigger when the app
          is in the background or terminated.

- `IosNotificationSettings`:

    - **DEPRECATED**: Usage of the `IosNotificationSettings` class is now deprecated (currently used with the now
      deprecated  `requestNotificationPermissions()` method).
        - Instead of this class, use named arguments when calling `requestPermission()` and read the permissions back
          via the returned `NotificationSettings` instance.

- `NotificationSettings`:

    - **NEW**: A `NotificationSettings` class is returned from calls to `requestPermission()`
      and `getNotificationSettings()`. It contains information such as the authorization status, along with the platform
      specific settings.

- `RemoteMessage`:

    - **NEW**: Incoming FCM payloads are now represented as a `RemoteMessage` rather than a raw `Map`.

- `RemoteNotification`:
    - **NEW**:When a message includes a notification payload, the `RemoteMessage` includes a `RemoteNotification` rather
      than a raw `Map`.

- **Other**:

    - Additional types are available throughout messaging to aid with the latest changes:
        - `BackgroundMessageHandler`, `AppleNotificationSetting`, `AppleShowPreviewSetting`, `AuthorizationStatus`
          , `AndroidNotificationPriority`, `AndroidNotificationVisibility`

### Remote Config

The plugin has been updated and reworked to better mirror the features
currently offered by the native (iOS and Android) clients.

`RemoteConfig`:
  - **CHORE**: migrate to platform interface.
  - **FEAT**: support multiple firebase apps. `RemoteConfig.instanceFor()` can
    be used to retrieve an instance of RemoteConfig for a particular
    Firebase App.
  - **BREAKING**: `fetch()` now takes no arguments. `RemoteConfigSettings` should
    be used to specify the freshness of the cached config via the `minimumFetchInterval`
    property.
  - **BREAKING**: `activateFetched()` is now `activate()`.
  - **FEAT**: Added `fetchAndActivate()` support.
  - **FEAT**: Added `ensureInitialized()` support.

`RemoteConfigSettings`
  - **BREAKING**: `fetchTimeoutMillis` is now `fetchTimeout`.
  - **BREAKING**: `minimumFetchIntervalMillis` is now `minimumFetchInterval`
  - **BREAKING**: `fetchTimeout` and `minimumFetchInterval` are refactored
    from `int` to `Duration`.

`FetchThrottledException`
  - **BREAKING**: removed `FetchThrottledException`. The general
    FirebaseException is used to handle all RemoteConfig specific exceptions.

### Storage

Overall, Firebase Storage has been heavily reworked to bring it inline with the federated plugin setup along with adding
new features, documentation and many more unit and end-to-end tests (tested on Android, iOS & macOS).

- **`FirebaseStorage`**:

    - **DEPRECATED**: Constructing an instance is now deprecated, use `FirebaseStorage.instanceFor`
      or `FirebaseStorage.instance` instead.
    - **DEPRECATED**: `getReferenceFromUrl()` is deprecated in favor of calling `ref()` with a path.
    - **DEPRECATED**: `getMaxOperationRetryTimeMillis()` is deprecated in favor of the getter `maxOperationRetryTime`.
    - **DEPRECATED**: `getMaxUploadRetryTimeMillis()` is deprecated in favor of the getter `maxUploadRetryTime`.
    - **DEPRECATED**: `getMaxDownloadRetryTimeMillis()` is deprecated in favor of the getter `maxDownloadRetryTime`.
    - **DEPRECATED**: `setMaxOperationRetryTimeMillis()` is deprecated in favor of `setMaxUploadRetryTime()`.
    - **DEPRECATED**: `setMaxUploadRetryTimeMillis()` is deprecated in favor of `setMaxUploadRetryTime()`.
    - **DEPRECATED**: `setMaxDownloadRetryTimeMillis()` is deprecated in favor of `setMaxDownloadRetryTime()`.
    - **NEW**: To match the Web SDK, calling `ref()` creates a new `Reference` at the bucket root, whereas an optional
      path (`ref('/foo/bar.png')`) can be used to create a `Reference` pointing at a specific location.
    - **NEW**: Added support for `refFromURL`, which accepts a Google Storage (`gs://`) or HTTP URL and returns
      a `Reference` synchronously.

- **`Reference`**:

    - **BREAKING**: `StorageReference` has been renamed to `Reference`.
    - **DEPRECATED**: `getParent()` is deprecated in favor of `.parent`.
    - **DEPRECATED**: `getRoot()` is deprecated in favor of `.root`.
    - **DEPRECATED**: `getStorage()` is deprecated in favor of `.storage`.
    - **DEPRECATED**: `getBucket()` is deprecated in favor of `.bucket`.
    - **DEPRECATED**: `getPath()` is deprecated in favor of `.fullPath`.
    - **DEPRECATED**: `getName()` is deprecated in favor of `.name`.
    - **NEW**: Added support for `list(options)`.
        - Includes `ListOptions` API (see below).
    - **NEW**: Added support for `listAll()`.
    - **NEW**: `putString()` has been added to accept a string value, of type Base64, Base64Url,
      a [Data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) or raw strings.
        - Data URLs automatically set the `Content-Type` metadata if not already set.
    - **NEW**: `getData()` does not require a `maxSize`, it can now be called with a default of 10mb.

- **NEW `ListOptions`**:

    - The `list()` method accepts a `ListOptions` instance with the following arguments:
        - `maxResults` - limits the number of results returned from a call. Defaults to 1000.
        - `pageToken`  - a page token returned from a `ListResult` - used if there are more items to query.

- **NEW `ListResult`**:

    - A `ListResult` class has been added, which is returned from a call to `list()` or `listAll()`. It exposes the
      following properties:
        - `items` (`List<Reference>`): Returns the list of reference objects at the current reference location.
        - `prefixes` (`List<Reference>`): Returns the list of reference sub-folders at the current reference location.
        - `nextPageToken` (`String`): Returns a string (or null) if a next page during a `list()` call exists.

- **Tasks**:
    - Tasks have been overhauled to be closer to the expected Firebase Web SDK Storage API, allowing users to access and
      control ongoing tasks easier. There are a number of breaking changes & features with this overhaul:
        - **BREAKING**: `StorageUploadTask` has been renamed to `UploadTask` (extends `Task`).
        - **BREAKING**: `StorageDownloadTask` has been renamed to `DownloadTask` (extends `Task`).
        - **BREAKING**: `StorageTaskEvent` has been removed (see below).
        - **BREAKING**: `StorageTaskSnapshot` has been renamed to `TaskSnapshot`.
        - **BREAKING**: `pause()`, `cancel()` and `resume()` are now Futures which return a boolean value to represent
          whether the status update was successful.
            - Previously, these were `void` methods but still carried out an asynchronous tasks, potentially leading to
              uncaught exceptions.
        - **BREAKING**: `isCanceled`, `isComplete`, `isInProgress`, `isPaused` and `isSuccessful` have now been removed.
          Instead, you should subscribe to the stream (for paused/progress/complete/error events) or the task `Future`
          for task completion/errors.
        - Additionally, the latest `TaskSnapshot` now provides the latest `TaskState` via `task.snapshot.state`.
        - **BREAKING**: The `events` stream (now `snapshotEvents`) previously returned a `StorageTaskEvent`, containing
          a `StorageTaskEventType` and `StorageTaskSnapshot` Instead, the stream now returns a `TaskSnapshot` which
          includes the `state`.
        - **BREAKING**: A task failure and cancellation now throw a `FirebaseException` instead of a new event.
        - **DEPRECATED**: `events` stream is deprecated in favor of `snapshotEvents`.
        - **DEPRECATED**: `lastSnapshot` is deprecated in favor of `snapshot`.

#### Example

The new Tasks API matches the Web SDK API, for example:

```dart
UploadTask task = FirebaseStorage.instance.ref('/notes.text').putString('My notes!');

// Optional
task.snapshotEvents.listen((TaskSnapshot snapshot) {
  print('Snapshot state: ${snapshot.state}'); // paused, running, complete
  print('Progress: ${snapshot.totalBytes / snapshot.bytesTransferred}');
}, onError: (Object e) {
  print(e); // FirebaseException
});

// Optional
task
  .then((TaskSnapshot snapshot) {
    print('Upload complete!');
  })
  .catchError((Object e) {
    print(e); // FirebaseException
  });
```

Subscribing to Stream updates and/or the tasks delegating Future is optional - if you require progress updates on your
task use the Stream, otherwise the Future will resolve once it's complete. Using both together is also supported.

## Common Upgrade Issues

### CocoaPods could not find compatible versions for pod

This issue can happen when you upgrade your FlutterFire packages and attempt to build for iOS or macOS, this is usually
down to one of the following:

- Your `Podfile.lock` version inside your iOS or macOS directory is out of date and locked to older versions of the
  Firebase iOS SDKs whereas the newly upgraded FlutterFire packages might be using newer versions of these SDKs.
    - **Solution:** Delete the `Podfile.lock` file and try your build again. This file will get regenerated after the
      next `pod install`.
- Your pod specs repo is out of date, meaning CocoaPods locally isn't aware of any potential newer versions of the
  Firebase iOS SDKs that have been recently published.
    - **Solution:** Run `pod repo update` in your terminal and try your build again.
